package cn.lxh.basic.service.impl;

import cn.lxh.basic.constant.BaseConstant;
import cn.lxh.basic.dto.RegisterDto;
import cn.lxh.basic.exception.BusinessException;
import cn.lxh.basic.service.IVerifyCodeService;
import cn.lxh.basic.utils.SmsUtils;
import cn.lxh.basic.utils.StrUtils;
import cn.lxh.basic.utils.VerifyCodeUtils;
import cn.lxh.user.domain.User;
import cn.lxh.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;



    @Override
    public String imageCode(String key) {
        if(!StringUtils.hasLength(key)){
            throw new BusinessException("key不能为空！！！");
        }
//        (每次都是直接生成新的，但是要覆盖前面的)
//        。生成code = 9527
        String code = StrUtils.getComplexRandomString(4);
//        。保存redis，设置过期时间  key是什么==前端请求给我传递的UUID
        redisTemplate.opsForValue().set(key,//前端传递的UUID
                code, //图片中的码儿
                5,//过期时间
                TimeUnit.MINUTES);//过期时间的单位
//        。使用2D引擎把code画成图
//        。把图使用Base64编码成字符串
//        。返回Base64编码的字符串
        return VerifyCodeUtils.VerifyCode(100,40,code);

    }


    @Override
    public void smsCode(RegisterDto dto) throws Exception {
        //前期准备 前端需要将图形验证码传过来  key和value
        String phone = dto.getPhone();
        String imageCodeValue = dto.getImageCodeValue();
        String imageCodeKey = dto.getImageCodeKey();
        /*
        空检验
         */
        if(StringUtils.isEmpty(phone)||StringUtils.isEmpty(imageCodeKey)||StringUtils.isEmpty(imageCodeValue)){
            throw new BusinessException("你的电话是空的或者你的没有输入图形验证码");
        }
       //2.校验图形验证码，根据imageCodeKey从redis获取图形验证码?根据key拿到 value值
        //注意拼接
        Object imageCodeKey1 = redisTemplate.opsForValue().get(imageCodeKey);
        //拿到图像的value值。
        if (imageCodeKey1 == null){
            throw new BusinessException("这个图片不对经。。过期了或者就根本没有");
        }
        // 。获取到了，比对图形验证码是否正确 (obj类型 使用string类型) 比对不要区分大小写  图片判断逻辑  注意拼接
        if(!imageCodeKey1.toString().equalsIgnoreCase(imageCodeValue)){
                throw new BusinessException("输入的验证码不正确");
        }
        //正确了--开始短信验证码的验证
        // 3.校验手机号是否注册过了
        User userTmp = userMapper.findByPhone(phone);
            //3.1没有别注册过  能找到这个user 对象
            //已近被注册过了
        if(userTmp != null){
            throw new BusinessException("这个号码已经被注册过了，换个号再来吧");
        }
        //3.1没有别注册过  能找到这个user 对象 那么就需要执行注册流程了：拼接。REGISTER+phone是key
        // 分两次。第一次来。。和第二次来。                                 验证码+currentTime当前时间。
        String key = BaseConstant.RegisterConstants.REGISTER_SMS_PREFIX + phone;
            //验证码和后面的vulue值；；注意spit
        Object smsCodeTmp = redisTemplate.opsForValue().get(key);
        //短息验证码过期了
        String  smsCode = "";
        if(smsCodeTmp !=null){
            //时间进行判断-强转
            Long oldTime = Long.valueOf(smsCodeTmp.toString().split(":")[1]);
            //小于一分钟
            if(System.currentTimeMillis() - oldTime <= 1*60*1000){
                throw new BusinessException("太着急了。请等待1分钟后再发送");
            }
            smsCode = smsCodeTmp.toString().split(":")[0];//9527
            //不让我用else 全局变量就好了
        }
        else{
//        1.2 获取不到
//        1.2.1.生成新的短信验证码
            smsCode = StrUtils.getComplexRandomString(4);
        }
//        3.存储redis 设置一个过期时间
        String smsCodeValue = smsCode + ":" + System.currentTimeMillis();
        redisTemplate.opsForValue().set(
                key,
                smsCodeValue,
                3,
                TimeUnit.MINUTES
        );
//        4.发送短信
        SmsUtils.sendSms(phone,"亲，您的验证码是："+smsCode+"。请在3分钟内使用！！");
        System.out.println("亲，您的验证码是：" + smsCode + "。请在3分钟内使用！！");
    }
}
